package cn.xzqwjw.taskmanager.security;

import cn.xzqwjw.taskmanager.common.customEnum.ResponseCodeEnum;
import cn.xzqwjw.taskmanager.utils.JwtUtil;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.www.NonceExpiredException;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 这是验证每个request的Jwt的核心验证器
 *
 * @author rush
 */
public class JwtAuthProvider implements AuthenticationProvider {

  @Override
  public boolean supports(Class<?> authentication) {
    return authentication.isAssignableFrom(TokenJwt.class);
  }

  /**
   * 验证的核心方法
   */
  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    // 首先从传过来的 JwtAuthenticationToken 中得到 jwt 字符串
    String jwtString = ((TokenJwt) authentication).getJwtString();
    if (!StringUtils.hasLength(jwtString)) {
      throw new InsufficientAuthenticationException(ResponseCodeEnum.JWT_NONCE.getMessage());
    }
    // 判断 jwt 格式是否正确
    if (!JwtUtil.isChecked(jwtString)) {
      throw new BadCredentialsException(ResponseCodeEnum.JWT_BAD_CHECK.getMessage());
    }
    // 判断 jwt 是否过期
    if (JwtUtil.isExpired(jwtString)) {
      throw new NonceExpiredException(ResponseCodeEnum.JWT_EXPIRATION.getMessage());
    }
    // 得到 jwt 里带的 username
    String username = JwtUtil.getUsername(jwtString);
    // 定义一个存放所有角色和权限的list
    List<GrantedAuthority> listGrantedAuthority = new ArrayList<>();
    String roles, purviews;
    String[] listRoles, listPurviews;
    // 得到 jwt 里带的 roles 和 purviews
    roles = JwtUtil.getRoles(jwtString);
    if (StringUtils.hasLength(roles)) {
      listRoles = roles.split(",");
      for (String r : listRoles) {
        listGrantedAuthority.add(new SimpleGrantedAuthority(r));
      }
    }
    purviews = JwtUtil.getPurviews(jwtString);
    if (StringUtils.hasLength(purviews)) {
      listPurviews = purviews.split(",");
      for (String p : listPurviews) {
        listGrantedAuthority.add(new SimpleGrantedAuthority(p));
      }
    }
    // 验证成功后返回重新包装过的 JwtAuthenticationToken
    // filter 会将这个 JwtAuthenticationToken 放入 SecurityContext
    return new TokenJwt(username, jwtString, listGrantedAuthority);
  }

}
